<?php

/**
 * Created by PhpStorm.
 * User: 29631
 * Date: 2017-12-18
 * Time: 9:54
 */
class protocol_writer
{
    function type_dynsize($v, &$b)
    {
        if ($v <= 0X3F)
            array_push($b, pack('C', $v));
        else if ($v <= 0X3FFF) {
            $v |= (1 << 14);
            array_push($b, pack('n', $v));
        } else if ($v <= 0X3FFFFF) {
            $v |= (2 << 22);
            array_push($b, substr(pack('C3', $v),1));
        } else if ($v <= 0X3FFFFFFF) {
            $v |= (3 << 30);
            array_push($b, pack('N', $v));
        }
    }

    function type_int64($v, &$b)
    {
        array_push($b, pack('q', $v));
    }

    function type_uint64($v, &$b)
    {
        array_push($b, pack('Q', $v));
    }

    function type_double($v, &$b)
    {
        array_push($b, pack('d', $v));
    }

    function type_float($v, &$b)
    {
        array_push($b, pack('f', $v));
    }

    function type_int32($v, &$b)
    {
        array_push($b, pack('i', $v));
    }

    function type_uint32($v, &$b)
    {
        array_push($b, pack('I', $v));
    }

    function type_int16($v, &$b)
    {
        array_push($b, pack('s', $v));
    }

    function type_uint16($v, &$b)
    {
        array_push($b, pack('S', $v));
    }

    function type_int8($v, &$b)
    {
        array_push($b, pack('c', $v));
    }

    function type_uint8($v, &$b)
    {
        array_push($b, pack('C', $v));
    }

    function type_string($v, &$b)
    {
        $len = strlen($v);
        $this->type_dynsize($len, $b);
        array_push($b, $v);
    }

    function type_binary($v, &$b)
    {
        $this->type_string($v, $b);
    }

    function type_mid($v, &$b)
    {
        $this->type_uint16($v, $b);
    }

    function type_enum($v, &$b)
    {
        $this->type_uint8($v, $b);
    }
	
	function type_enum16($v, &$b)
    {
        $this->type_uint16($v, $b);
    }

    function type_bool($v, &$b)
    {
        array_push($b, $v ? chr(1) : chr(0));
    }

    function write($func, $assoc, $v, &$b)
    {
        if ($assoc) {
            $len = count($v);
            $this->type_dynsize($len, $b);
            $idx = 0;
            while ($idx < $len) {
                call_user_func_array($func, array($v[$idx], &$b));
                ++$idx;
            }
        } else {
            call_user_func_array($func, array($v, &$b));
        }
    }
}
